package pri.damai.xiaowu.anydoor.netty;

import com.google.common.collect.Lists;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import pri.damai.xiaowu.anydoor.netty.codec.BizModelDecoder;
import pri.damai.xiaowu.anydoor.netty.codec.BizModelEncoder;
import pri.damai.xiaowu.anydoor.business.ModelHolder;
import pri.damai.xiaowu.anydoor.netty.handler.*;

import java.io.IOException;
import java.util.List;

/**
 *  netty 服务端
 *
 * @description
 *          协议: |标识:4个字节|指令:1个字节|长度:4个字节|消息体|
 * @author YangXinFu
 * @date 9:19 2022/7/25
 **/
public class NettyServer {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {

        ModelHolder.initModel();

        new NettyServer().bind(4466, Lists.newArrayList(
                new BizModelHandler(),
                new RobustHandler(),
                new WebSocketFrameHandler(),
                new WebSocketHttpHandler()
        ));

    }

    public void bind(int port, List<ChannelInboundHandlerAdapter> handlers) {
        // 配置服务端 NIO 线程组
        NioEventLoopGroup parentGroup = new NioEventLoopGroup();
        NioEventLoopGroup childGroup = new NioEventLoopGroup();

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(parentGroup, childGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
//                        channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 5, 4));
//                        channel.pipeline().addLast(new BizModelDecoder());
//                        channel.pipeline().addLast(new HttpServerCodec());
//                        channel.pipeline().addLast(new HttpObjectAggregator(65536));
//                        channel.pipeline().addLast((ChannelHandler) new ChunkedWriteHandler());
//                        channel.pipeline().addLast(handlers.toArray(new ChannelInboundHandlerAdapter[0]));
//                        channel.pipeline().addLast(new BizModelEncoder());
                        ch.pipeline().addLast("logging",new LoggingHandler("DEBUG"));//设置log监听器，并且日志级别为debug，方便观察运行流程
                        ch.pipeline().addLast("http-codec",new HttpServerCodec());//设置解码器
                        ch.pipeline().addLast("aggregator",new HttpObjectAggregator(65536));//聚合器，使用websocket会用到
                        ch.pipeline().addLast("http-chunked",new ChunkedWriteHandler());//用于大数据的分区传输
                        ch.pipeline().addLast("handler",new WebSocketDemoHandler());//自定义的业务handler
                    }
                });

        ChannelFuture sync = null;
        try {
            sync = bootstrap.bind(port).sync();
            System.out.println("Netty服务端启动完毕。");
            sync.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            childGroup.shutdownGracefully();
            parentGroup.shutdownGracefully();
        }


    }

}
